home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Utilities / Remotes / Source / HostListManager.m < prev    next >
Encoding:
Text File  |  1992-09-23  |  41.3 KB  |  1,341 lines

  1. /*---------------------------------------------------------------------------
  2. HostListManager.m -- Copyright (c) 1991 Rex Pruess
  3.   
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.   
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.   
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA or send
  17.    electronic mail to the the author.
  18.   
  19. This is the methods file for the HostListManager (HLM) class.  A HLM object is
  20. responsible for managing the internal linked host list and the host
  21. configuration file.
  22.   
  23. Rex Pruess <rpruess@umaxc.weeg.uiowa.edu>
  24.   
  25. $Header: /rpruess/apps/Remotes3.0/RCS/HostListManager.m,v 3.0 92/09/23 21:49:40 rpruess Exp $
  26. -----------------------------------------------------------------------------
  27. $Log:    HostListManager.m,v $
  28. Revision 3.0  92/09/23  21:49:40  rpruess
  29. Upgraded for NeXT System Release 3.0.  Primary changes were to support the
  30. Terminal application under NeXT System Release 3.0.
  31.  
  32. Revision 2.1  92/09/21  11:20:13  rpruess
  33. Added code to set the window title and mini-window titles for Stuart
  34. sessions.
  35.  
  36. Revision 2.0  91/01/22  15:32:47  rpruess
  37. Remotes-2.0 was upgraded for NeXT System Release 2.0 (standard or extended).
  38. Remotes-2.0 supports the NeXT supplied Terminal application and the Stuart
  39. shareware product.
  40.  
  41. Revision 1.1  90/04/10  14:25:48  rpruess
  42. Initial revision
  43.  
  44. -----------------------------------------------------------------------------*/
  45.  
  46. /* Standard C header files */
  47. #include <ctype.h>
  48. #include <libc.h>
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <strings.h>
  52. #include <sys/file.h>
  53.  
  54. /* Private C header files */
  55. #include "remsubs.h"
  56.  
  57. /* Host List Manager class header files */
  58. #import "HostListManager.h"
  59. #import "StuartSpeaker.h"
  60.  
  61. /* Appkit header files */
  62. #import <appkit/Application.h>
  63. #import <appkit/Control.h>
  64. #import <appkit/Panel.h>
  65. #import <appkit/PopUpList.h>
  66.  
  67. #import <defaults/defaults.h>
  68.  
  69. @implementation HostListManager
  70.  
  71. /*---------------------------------------------------------------------------
  72. Override the new method so the object can be properly initialized.  This
  73. initialization includes reading the configuration file & loading the hosts
  74. into the internal linked list.
  75. -----------------------------------------------------------------------------*/
  76. - init
  77. {   
  78.    self = [super init];
  79.  
  80.    [self initHLMObject:self];   /* Initialize linked host lists */
  81.    return self;
  82. }
  83.  
  84. /*---------------------------------------------------------------------------
  85. Initialize the host list.
  86. -----------------------------------------------------------------------------*/
  87. - initHLMObject:sender
  88. {
  89.    short int       appType;
  90.    short int       autoLaunch;
  91.    char            buffer[MAXRECLEN + 1];
  92.    char           *bufPtr;
  93.    char            buttonName[MAXPOPLEN + 1];
  94.    const char     *defaultsDebugLevel;
  95.    int             code;
  96.    short int       columns;
  97.    char            field[MAXRECLEN + 1];
  98.    unsigned int    flagValues;
  99.    short int       fontType;
  100.    short int       fontSize;
  101.    char            hName[MAXHOSTNAMELEN + 1];
  102.    int             i;
  103.    short int       lines;
  104.    short int       metaNum;
  105.    BOOL            oldStyle;
  106.    short int       protocolType;
  107.    int             recordNum;
  108.    NXSize          screenSize;  /* Screen width/height */
  109.    char            userID[MAXIDLEN + 1];
  110.    short int       versionNum;
  111.    short int       x;
  112.    short int       y;
  113.    FILE           *fp;
  114.  
  115.    /* Set debugging value from defaults data base */
  116.    defaultsDebugLevel = NXGetDefaultValue ([NXApp appName], "DebugLevel");
  117.  
  118.    if (strcmp (defaultsDebugLevel, "low") == 0)
  119.       debugLevel = DEBUGLOW;
  120.    else if (strcmp (defaultsDebugLevel, "high") == 0)
  121.       debugLevel = DEBUGHIGH;
  122.    else if (strcmp (defaultsDebugLevel, "max") == 0)
  123.       debugLevel = DEBUGMAX;
  124.    else
  125.       debugLevel = DEBUGOFF;
  126.  
  127.    /* Load linked host list. */
  128.    recordNum = 0;
  129.    nHosts = 0;
  130.  
  131.    fp = [self openConfigFile:"r"];
  132.  
  133.    if (fp == NULL) {            /* In no hosts found, then force one! */
  134.       code = [self addLocalHost:self];
  135.       return self;
  136.    }
  137.  
  138.    /* Read & process each record from the config file */
  139.    while (fgets (buffer, MAXRECLEN, fp) != NULL) {
  140.       bufPtr = buffer;          /* Pointer to next field in buffer */
  141.       recordNum++;
  142.  
  143.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  144.          [self errPrint:"version number" recNum:recordNum];
  145.          continue;
  146.       }
  147.       field[MAXPOPLEN] = '\0';
  148.       
  149.       oldStyle = NO;        /* Old style config file has no version # */
  150.       for (i = 0; i < strlen (field); i++) {
  151.      if (isdigit (field[i]))
  152.         continue;
  153.      else {
  154.         oldStyle = YES;
  155.         break;
  156.      }
  157.       }
  158.       
  159.       if (oldStyle) {
  160.      versionNum = 0;
  161.      strcpy (buttonName, field);
  162.       }
  163.       else {
  164.      versionNum = atoi (field);
  165.      
  166.      if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  167.         [self errPrint:"button name" recNum:recordNum];
  168.         continue;
  169.      }
  170.      field[MAXPOPLEN] = '\0';
  171.      strcpy (buttonName, field);
  172.       }
  173.       
  174.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  175.          [self errPrint:"hostname" recNum:recordNum];
  176.          continue;
  177.       }
  178.       field[MAXHOSTNAMELEN] = '\0';
  179.       strcpy (hName, field);
  180.  
  181.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  182.          [self errPrint:"user ID" recNum:recordNum];
  183.          continue;
  184.       }
  185.       field[MAXIDLEN] = '\0';
  186.       strcpy (userID, field);
  187.  
  188.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  189.          [self errPrint:"application" recNum:recordNum];
  190.          continue;
  191.       }
  192.       appType = atoi (field);
  193.       if (appType != TERMINAL && appType != STUART) {
  194.          [self errPrint:"application" recNum:recordNum];
  195.          continue;
  196.       }
  197.  
  198.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  199.          [self errPrint:"protocol" recNum:recordNum];
  200.          continue;
  201.       }
  202.       protocolType = atoi (field);
  203.       if (protocolType != RLOGIN && protocolType != TELNET
  204.          && protocolType != TN3270) {
  205.          [self errPrint:"protocol" recNum:recordNum];
  206.          continue;
  207.       }
  208.  
  209.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  210.          [self errPrint:"x" recNum:recordNum];
  211.          continue;
  212.       }
  213.       x = atoi (field);
  214.  
  215.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  216.          [self errPrint:"y" recNum:recordNum];
  217.          continue;
  218.       }
  219.       y = atoi (field);
  220.       
  221.       /* In old version, Y was measured from top of display. */
  222.       if (versionNum == 0 && y < 300) {
  223.      [NXApp getScreenSize:&screenSize];
  224.      y = screenSize.height - y;
  225.       }
  226.       
  227.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  228.          [self errPrint:"lines" recNum:recordNum];
  229.          continue;
  230.       }
  231.       lines = atoi (field);
  232.  
  233.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  234.          [self errPrint:"columns" recNum:recordNum];
  235.          continue;
  236.       }
  237.       columns = atoi (field);
  238.  
  239.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  240.          [self errPrint:"font type" recNum:recordNum];
  241.          continue;
  242.       }
  243.       fontType = atoi (field);
  244.       if (fontType != COURIER && fontType != OHLFS) {
  245.          [self errPrint:"font type" recNum:recordNum];
  246.          continue;
  247.       }
  248.  
  249.       if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  250.          [self errPrint:"font size" recNum:recordNum];
  251.          continue;
  252.       }
  253.       fontSize = atoi (field);
  254.  
  255.       if ((bufPtr = getfield (bufPtr, field)) == NULL)
  256.          autoLaunch = NO;
  257.       else
  258.          autoLaunch = atoi (field);
  259.  
  260.       if (appType == TERMINAL)
  261.      flagValues = TTRANSLAT | TAUTOWRAP | TSCROLLBK;
  262.       else
  263.      flagValues = SSCROLLBK | STRANSLAT | STERMSPAC;
  264.       
  265.       metaNum = METAESC;
  266.  
  267.       if (versionNum == CFGVERSION) {
  268.      if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  269.         [self errPrint:"flag values" recNum:recordNum];
  270.         continue;
  271.      }
  272.      flagValues = atoi (field);
  273.  
  274.      if ((bufPtr = getfield (bufPtr, field)) == NULL) {
  275.         [self errPrint:"meta number" recNum:recordNum];
  276.         continue;
  277.      }
  278.      metaNum = atoi (field);
  279.       }
  280.      
  281.       code = [self addHost:buttonName fullHostName:hName loginName:userID
  282.          application:appType protocol:protocolType locX:x locY:y
  283.          nLines:lines nCols:columns font:fontType fontSize:fontSize
  284.          autoStart:autoLaunch flags:flagValues meta:metaNum
  285.      updateConfigFile:NO];
  286.  
  287.       if (debugLevel == DEBUGMAX) {
  288.          printf ("%s:(read #%d okay) version:%d\t%s\t%s\n",[NXApp appName],
  289.             recordNum, versionNum, buttonName, hName);
  290.          printf ("\tID:%s", userID);
  291.          printf ("\tapp:%d", appType);
  292.          printf ("\tprot:%d", protocolType);
  293.          printf ("\tx:%d", x);
  294.          printf ("\ty:%d", y);
  295.          printf ("\n");
  296.          printf ("\tlines:%d", lines);
  297.          printf ("\tcols:%d", columns);
  298.          printf ("\tfont:%d", fontType);
  299.          printf ("\tfontsize:%d", fontSize);
  300.          printf ("\n");
  301.          printf ("\tautostart:%d", autoLaunch);
  302.          printf ("\tflags:%u", flagValues);
  303.          printf ("\tmeta:%d", metaNum);
  304.          printf ("\n");
  305.       }
  306.    }
  307.  
  308.    fclose (fp);
  309.  
  310.    if (debugLevel >= DEBUGHIGH)
  311.       printf ("%s: %d records successfully read from config file.\n",
  312.          [NXApp appName], nHosts);
  313.  
  314.    return self;
  315. }
  316.  
  317. /*---------------------------------------------------------------------------
  318. Stuff an entry into the doubly linked circular list of hosts.  The head and
  319. tail entries point to each other so a true circular loop is maintained & thus
  320. simplifies coding.  Duplicates are not entered.  This routine returns the slot
  321. number where the host was inserted.  The list is maintained in alphabetical
  322. order.
  323. -----------------------------------------------------------------------------*/
  324. - (int)insert:(struct hostEntry *) newEntry
  325. {
  326.    int             slotNum;     /* Slot position of host in linked list */
  327.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  328.  
  329.    /* First entry in the list.  Point to myself. */
  330.    if (nHosts == 0) {
  331.       newEntry -> nextHost = newEntry;
  332.       newEntry -> prevHost = newEntry;
  333.       begHost = newEntry;       /* Set beginning host pointer too. */
  334.       nHosts++;
  335.       return 0;
  336.    }
  337.  
  338.    /* Find spot that this entry must be inserted at. */
  339.    hostPtr = begHost;
  340.    for (slotNum = 0; slotNum < nHosts; slotNum++) {
  341.       if (strcmp (newEntry -> popUpName, hostPtr -> popUpName) < 0)
  342.          break;
  343.       if (strcmp (newEntry -> popUpName, hostPtr -> popUpName) == 0)
  344.          return -1;
  345.       hostPtr = hostPtr -> nextHost;
  346.    }
  347.  
  348.    /* Entry is at head of list.  Adjust beginning host pointer too. */
  349.    if (slotNum == 0)
  350.       begHost = newEntry;
  351.  
  352.    /* Set new entry's next & previous pointers */
  353.    newEntry -> nextHost = hostPtr;
  354.    newEntry -> prevHost = hostPtr -> prevHost;
  355.  
  356.    /* Set previous host's "next pointer" */
  357.    hostPtr -> prevHost -> nextHost = newEntry;
  358.  
  359.    /* Set next host's "previous pointer" */
  360.    hostPtr -> prevHost = newEntry;
  361.  
  362.    nHosts++;
  363.  
  364.    return slotNum;
  365. }
  366.  
  367. /*---------------------------------------------------------------------------
  368. Print error message about bad input record in configuration file.
  369. -----------------------------------------------------------------------------*/
  370. - errPrint:(char *)fieldName recNum:(int)recordNum
  371. {
  372.    printf ("%s:Invalid %s field in record %d in config file.\n",
  373.       [NXApp appName], fieldName, recordNum);
  374.    return self;
  375. }
  376.  
  377. /*---------------------------------------------------------------------------
  378. Add a host into the internal linked list.
  379. -----------------------------------------------------------------------------*/
  380. - (int)addHost:(const char *)buttonName
  381.    fullHostName:(const char *)fullName
  382.    loginName:(const char *)userID
  383.    application:(short int)app
  384.    protocol:(short int)prot
  385.    locX:(short int)x
  386.    locY:(short int)y
  387.    nLines:(short int)lines
  388.    nCols:(short int)columns
  389.    font:(short int)aFont
  390.    fontSize:(short int)fontNum
  391.    autoStart:(short int)autoLaunch
  392.    flags:(unsigned int)flagValues
  393.    meta:(short int)metaNum
  394.    updateConfigFile:(short int)updConfigFile
  395. {
  396.    int             slotNum;     /* Slot position of host in linked list */
  397.    struct hostEntry *newEntry;  /* Pointer to host entry */
  398.    FILE           *fp;
  399.  
  400.    newEntry = malloc (HOSTENTRYLEN);
  401.  
  402.    strcpy (newEntry -> popUpName, buttonName);
  403.    strcpy (newEntry -> hostName, fullName);
  404.    strcpy (newEntry -> loginName, userID);
  405.    newEntry -> appType = app;
  406.    newEntry -> protocolType = prot;
  407.    newEntry -> locX = x;
  408.    newEntry -> locY = y;
  409.    newEntry -> nLines = lines;
  410.    newEntry -> nCols = columns;
  411.    newEntry -> fontType = aFont;
  412.    newEntry -> fontSize = fontNum;
  413.    newEntry -> autoStart = autoLaunch;
  414.    newEntry -> flags = flagValues;
  415.    newEntry -> meta = metaNum;
  416.  
  417.    slotNum = [self insert:newEntry];
  418.  
  419.    if (slotNum < 0 || updConfigFile == NO)
  420.       return slotNum;
  421.  
  422.    fp = [self openConfigFile:"a"];
  423.  
  424.    if (fp != NULL) {
  425.       fprintf (fp, "%d", CFGVERSION);      
  426.       fprintf (fp, "\t%s", buttonName);
  427.       fprintf (fp, "\t%s", fullName);
  428.       fprintf (fp, "\t%s", userID);
  429.       fprintf (fp, "\t%d", app);
  430.       fprintf (fp, "\t%d", prot);
  431.       fprintf (fp, "\t%d", x);
  432.       fprintf (fp, "\t%d", y);
  433.       fprintf (fp, "\t%d", lines);
  434.       fprintf (fp, "\t%d", columns);
  435.       fprintf (fp, "\t%d", aFont);
  436.       fprintf (fp, "\t%d", fontNum);
  437.       fprintf (fp, "\t%d", autoLaunch);
  438.       fprintf (fp, "\t%u", flagValues);
  439.       fprintf (fp, "\t%d", metaNum);
  440.       fprintf (fp, "\n");
  441.    }
  442.  
  443.    fclose (fp);
  444.  
  445.    if (debugLevel >= DEBUGHIGH)
  446.       printf ("%s: Record added to config file.\n",[NXApp appName]);
  447.  
  448.    if (debugLevel == DEBUGMAX) {
  449.       printf ("%s:(append okay) version:%d\t%s\t%s\n",
  450.          [NXApp appName], CFGVERSION, buttonName, fullName);
  451.       printf ("\tID:%s", userID);
  452.       printf ("\tapp:%d", app);
  453.       printf ("\tprot:%d", prot);
  454.       printf ("\tx:%d", x);
  455.       printf ("\ty:%d", y);
  456.       printf ("\n");
  457.       printf ("\tlines:%d", lines);
  458.       printf ("\tcols:%d", columns);
  459.       printf ("\tfont:%d", aFont);
  460.       printf ("\tfontsize:%d", fontNum);
  461.       printf ("\n");
  462.       printf ("\tautostart:%d", autoLaunch);
  463.       printf ("\tflags:%u", flagValues);
  464.       printf ("\tmeta:%d", metaNum);
  465.       printf ("\n");
  466.    }
  467.  
  468.    return slotNum;
  469. }
  470.  
  471. /*---------------------------------------------------------------------------
  472. Add a default Terminal & Stuart entry.  Use values in the defaults data base
  473. for the various fields.
  474. -----------------------------------------------------------------------------*/
  475. - (int)addLocalHost:sender
  476. {
  477.    short int       columns;
  478.    short int       lines;
  479.    unsigned int    flagValues;
  480.    short int       fontNum;
  481.    short int       fontStyle;
  482.    int             slotNum;     /* Slot position of host in linked list */
  483.    const char     *string;      /* Temporary variable */
  484.  
  485.    string = NXGetDefaultValue ("Terminal", "Columns");
  486.    columns = atoi (string);
  487.  
  488.    string = NXGetDefaultValue ("Terminal", "Rows");
  489.    lines = atoi (string);
  490.  
  491.    string = NXGetDefaultValue ("Terminal", "NXFixedPitchFontSize");
  492.    fontNum = atoi (string);
  493.  
  494.    string = NXGetDefaultValue ("Terminal", "NXFixedPitchFont");
  495.    if (strcmp (string, "Courier") == 0)
  496.       fontStyle = COURIER;
  497.    else
  498.       fontStyle = OHLFS;
  499.  
  500.    flagValues = TTRANSLAT | TAUTOWRAP | TSCROLLBK | TSOURCEDL;
  501.  
  502.    slotNum = [self addHost:"Terminal" fullHostName:"localhost" loginName:""
  503.       application:TERMINAL protocol:RLOGIN locX:120 locY:832 nLines:lines
  504.       nCols:columns font:fontStyle fontSize:fontNum
  505.       autoStart:NO flags:flagValues meta:METAESC updateConfigFile:YES];
  506.  
  507.    string = NXGetDefaultValue ("Stuart", "Columns");
  508.    columns = atoi (string);
  509.  
  510.    string = NXGetDefaultValue ("Stuart", "Lines");
  511.    lines = atoi (string);
  512.  
  513.    string = NXGetDefaultValue ("Stuart", "NXFixedPitchFontSize");
  514.    fontNum = atoi (string);
  515.  
  516.    string = NXGetDefaultValue ("Stuart", "NXFixedPitchFont");
  517.    if (strcmp (string, "Courier") == 0)
  518.       fontStyle = COURIER;
  519.    else
  520.       fontStyle = OHLFS;
  521.  
  522.    flagValues = SSCROLLBK | STRANSLAT | STERMSPAC | SSOURCEDL;
  523.    slotNum = [self addHost:"Stuart" fullHostName:"localhost" loginName:""
  524.       application:STUART protocol:RLOGIN locX:130 locY:832 nLines:lines
  525.       nCols:columns font:fontStyle fontSize:fontNum
  526.       autoStart:NO flags:flagValues meta:METAESC updateConfigFile:YES];
  527.  
  528.    return slotNum;
  529. }
  530.  
  531. /*---------------------------------------------------------------------------
  532. Change values in an existing host entry.
  533. -----------------------------------------------------------------------------*/
  534. - (int)changeHost:(const char *)buttonName
  535.    fullHostName:(const char *)fullName
  536.    loginName:(const char *)userID
  537.    application:(short int)app
  538.    protocol:(short int)prot
  539.    locX:(short int)x
  540.    locY:(short int)y
  541.    nLines:(short int)lines
  542.    nCols:(short int)columns
  543.    font:(short int)aFont
  544.    fontSize:(short int)fontNum
  545.    autoStart:(short int)autoLaunch
  546.    flags:(unsigned int)flagValues
  547.    meta:(short int)metaNum
  548. {
  549.    int             i;
  550.    int             slotNum;     /* Slot position of host in linked list */
  551.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  552.  
  553.    slotNum = [self getHostSlotNum:buttonName];
  554.    if (slotNum < 0)
  555.       return slotNum;
  556.  
  557.    /* Find the host in our list */
  558.    hostPtr = begHost;
  559.    for (i = 0; i < slotNum; i++)
  560.       hostPtr = hostPtr -> nextHost;
  561.  
  562.    strcpy (hostPtr -> popUpName, buttonName);
  563.    strcpy (hostPtr -> hostName, fullName);
  564.    strcpy (hostPtr -> loginName, userID);
  565.    hostPtr -> appType = app;
  566.    hostPtr -> protocolType = prot;
  567.    hostPtr -> locX = x;
  568.    hostPtr -> locY = y;
  569.    hostPtr -> nLines = lines;
  570.    hostPtr -> nCols = columns;
  571.    hostPtr -> fontType = aFont;
  572.    hostPtr -> fontSize = fontNum;
  573.    hostPtr -> autoStart = autoLaunch;
  574.    hostPtr -> flags = flagValues;
  575.    hostPtr -> meta = metaNum;
  576.  
  577.    [self writeConfigFile:self];
  578.  
  579.    return slotNum;
  580. }
  581.  
  582. /*---------------------------------------------------------------------------
  583. Delete a host entry from the internal linked list & from the file.
  584. -----------------------------------------------------------------------------*/
  585. - (int)deleteHost:(int)slotNum
  586. {
  587.    int             i;
  588.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  589.  
  590.    hostPtr = begHost;
  591.  
  592.    if (slotNum == 0)
  593.       begHost = hostPtr -> nextHost;    /* Head entry deletion */
  594.    else
  595.       for (i = 0; i < slotNum; i++)
  596.          hostPtr = hostPtr -> nextHost;
  597.  
  598.    hostPtr -> nextHost -> prevHost = hostPtr -> prevHost;
  599.    hostPtr -> prevHost -> nextHost = hostPtr -> nextHost;
  600.  
  601.    free (hostPtr);
  602.  
  603.    nHosts--;
  604.  
  605.    [self writeConfigFile:self];
  606.  
  607.    return slotNum;
  608. }
  609.  
  610. /*---------------------------------------------------------------------------
  611. Return the application type (e.g., Terminal, Stuart) for this slot.
  612. -----------------------------------------------------------------------------*/
  613. - (int)getAppType:(int)slotNum
  614. {
  615.    int             i;
  616.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  617.  
  618.    hostPtr = begHost;
  619.  
  620.    for (i = 0; i < slotNum; i++)
  621.       hostPtr = hostPtr -> nextHost;
  622.    return hostPtr -> appType;
  623. }
  624.  
  625. /*---------------------------------------------------------------------------
  626. Return the auto launch value for this slot.
  627. -----------------------------------------------------------------------------*/
  628. - (int)getAutoStart:(int)slotNum
  629. {
  630.    int             i;
  631.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  632.  
  633.    hostPtr = begHost;
  634.  
  635.    for (i = 0; i < slotNum; i++)
  636.       hostPtr = hostPtr -> nextHost;
  637.    return hostPtr -> autoStart;
  638. }
  639.  
  640. /*---------------------------------------------------------------------------
  641. Return the button name for the entry at the specified slot.
  642. -----------------------------------------------------------------------------*/
  643. - (char *)getButtonName:(int)slotNum
  644. {
  645.    int             i;
  646.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  647.  
  648.    hostPtr = begHost;
  649.    for (i = 0; i < slotNum; i++)
  650.       hostPtr = hostPtr -> nextHost;
  651.    return hostPtr -> popUpName;
  652. }
  653.  
  654. /*---------------------------------------------------------------------------
  655. Return the width for the entry at the specified slot.
  656. -----------------------------------------------------------------------------*/
  657. - (int)getColumns:(int)slotNum
  658. {
  659.    int             i;
  660.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  661.  
  662.    hostPtr = begHost;
  663.    for (i = 0; i < slotNum; i++)
  664.       hostPtr = hostPtr -> nextHost;
  665.    return hostPtr -> nCols;
  666. }
  667.  
  668. /*---------------------------------------------------------------------------
  669. Return the configuration pathname for the entry at the specified slot.
  670. -----------------------------------------------------------------------------*/
  671. - (const char *)getConfigFile:sender
  672. {
  673.    return NXGetDefaultValue ([NXApp appName], "ConfigFile");
  674. }
  675.  
  676. /*---------------------------------------------------------------------------
  677. Return the debugging level.
  678. -----------------------------------------------------------------------------*/
  679. - (int)getDebugLevel:sender
  680. {
  681.    return debugLevel;
  682. }
  683.  
  684. /*---------------------------------------------------------------------------
  685. Return the Stuart/Terminal flag values.
  686. -----------------------------------------------------------------------------*/
  687. - (unsigned int)getFlags:(int)slotNum
  688. {
  689.    int             i;
  690.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  691.  
  692.    hostPtr = begHost;
  693.  
  694.    for (i = 0; i < slotNum; i++)
  695.       hostPtr = hostPtr -> nextHost;
  696.    return hostPtr -> flags;
  697. }
  698.  
  699. /*---------------------------------------------------------------------------
  700. Return the font type for the entry at the specified slot.
  701. -----------------------------------------------------------------------------*/
  702. - (int)getFontType:(int)slotNum
  703. {
  704.    int             i;
  705.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  706.  
  707.    hostPtr = begHost;
  708.    for (i = 0; i < slotNum; i++)
  709.       hostPtr = hostPtr -> nextHost;
  710.    return hostPtr -> fontType;
  711. }
  712.  
  713. /*---------------------------------------------------------------------------
  714. Return the font size for the entry at the specified slot.
  715. -----------------------------------------------------------------------------*/
  716. - (int)getFontSize:(int)slotNum
  717. {
  718.    int             i;
  719.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  720.  
  721.    hostPtr = begHost;
  722.    for (i = 0; i < slotNum; i++)
  723.       hostPtr = hostPtr -> nextHost;
  724.    return hostPtr -> fontSize;
  725. }
  726.  
  727. /*---------------------------------------------------------------------------
  728. Return the complete host name for the entry at the specified slot.
  729. -----------------------------------------------------------------------------*/
  730. - (char *)getFullHostName:(int)slotNum
  731. {
  732.    int             i;
  733.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  734.  
  735.    hostPtr = begHost;
  736.  
  737.    for (i = 0; i < slotNum; i++)
  738.       hostPtr = hostPtr -> nextHost;
  739.    return hostPtr -> hostName;
  740. }
  741.  
  742. /*---------------------------------------------------------------------------
  743. Return the host slot number for the entry at the specified slot.
  744. -----------------------------------------------------------------------------*/
  745. - (int)getHostSlotNum:(const char *)buttonName
  746. {
  747.    int             i;
  748.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  749.  
  750.    hostPtr = begHost;
  751.    for (i = 0; i < nHosts; i++) {
  752.       if (strcmp (buttonName, hostPtr -> popUpName) == 0)
  753.          return i;
  754.       hostPtr = hostPtr -> nextHost;
  755.    }
  756.  
  757.    return -1;
  758. }
  759.  
  760. /*---------------------------------------------------------------------------
  761. Return the number of lines in the window for the entry at the specified slot.
  762. -----------------------------------------------------------------------------*/
  763. - (int)getLines:(int)slotNum
  764. {
  765.    int             i;
  766.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  767.  
  768.    hostPtr = begHost;
  769.    for (i = 0; i < slotNum; i++)
  770.       hostPtr = hostPtr -> nextHost;
  771.    return hostPtr -> nLines;
  772. }
  773.  
  774. /*---------------------------------------------------------------------------
  775. Return the meta value.
  776. -----------------------------------------------------------------------------*/
  777. - (int)getMeta:(int)slotNum
  778. {
  779.    int             i;
  780.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  781.  
  782.    hostPtr = begHost;
  783.    for (i = 0; i < slotNum; i++)
  784.       hostPtr = hostPtr -> nextHost;
  785.    return hostPtr -> meta;
  786. }
  787.  
  788. /*---------------------------------------------------------------------------
  789. Return the number of hosts in list.
  790. -----------------------------------------------------------------------------*/
  791. - (int)getNumHosts:sender
  792. {
  793.    return nHosts;
  794. }
  795.  
  796. /*---------------------------------------------------------------------------
  797. Return the popup button name for the entry at the specified slot.
  798. -----------------------------------------------------------------------------*/
  799. - (char *)getPopUpName:(int)slotNum
  800. {
  801.    int             i;
  802.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  803.  
  804.    hostPtr = begHost;
  805.  
  806.    for (i = 0; i < slotNum; i++)
  807.       hostPtr = hostPtr -> nextHost;
  808.    return hostPtr -> popUpName;
  809. }
  810.  
  811. /*---------------------------------------------------------------------------
  812. Return the protocol type (e.g., rlogin, telnet, tn3270).
  813. -----------------------------------------------------------------------------*/
  814. - (int)getProtocolType:(int)slotNum
  815. {
  816.    int             i;
  817.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  818.  
  819.    hostPtr = begHost;
  820.  
  821.    for (i = 0; i < slotNum; i++)
  822.       hostPtr = hostPtr -> nextHost;
  823.    return hostPtr -> protocolType;
  824. }
  825.  
  826. /*---------------------------------------------------------------------------
  827. Return the user ID for the entry at the specified slot.
  828. -----------------------------------------------------------------------------*/
  829. - (char *)getUserID:(int)slotNum
  830. {
  831.    int             i;
  832.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  833.  
  834.    hostPtr = begHost;
  835.  
  836.    for (i = 0; i < slotNum; i++)
  837.       hostPtr = hostPtr -> nextHost;
  838.    return hostPtr -> loginName;
  839. }
  840.  
  841. /*---------------------------------------------------------------------------
  842. Return the X coordinate for the entry at the specified slot.
  843. -----------------------------------------------------------------------------*/
  844. - (int)getX:(int)slotNum
  845. {
  846.    int             i;
  847.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  848.  
  849.    hostPtr = begHost;
  850.  
  851.    for (i = 0; i < slotNum; i++)
  852.       hostPtr = hostPtr -> nextHost;
  853.    return hostPtr -> locX;
  854. }
  855.  
  856. /*---------------------------------------------------------------------------
  857. Return the Y coordinate for the entry at the specified slot.
  858. -----------------------------------------------------------------------------*/
  859. - (int)getY:(int)slotNum
  860. {
  861.    int             i;
  862.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  863.  
  864.    hostPtr = begHost;
  865.  
  866.    for (i = 0; i < slotNum; i++)
  867.       hostPtr = hostPtr -> nextHost;
  868.    return hostPtr -> locY;
  869. }
  870.  
  871. /*---------------------------------------------------------------------------
  872. Load a popuplist.  This could be either the hosts popup list or the
  873. configuration pulldown list.
  874. -----------------------------------------------------------------------------*/
  875. - loadPopUpList:aPopUpList
  876. {
  877.    int             i;
  878.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  879.  
  880.    hostPtr = begHost;
  881.  
  882.    for (i = 0; i < nHosts; i++) {
  883.       [aPopUpList addItem:hostPtr -> popUpName];
  884.       hostPtr = hostPtr -> nextHost;
  885.    }
  886.  
  887.    return self;
  888. }
  889.  
  890. /*---------------------------------------------------------------------------
  891. Remotes is coming to life.  Launch those automatic startup guys.
  892. -----------------------------------------------------------------------------*/
  893. - autoStart:sender
  894. {
  895.    int             i;
  896.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  897.  
  898.    hostPtr = begHost;
  899.  
  900.    for (i = 0; i < nHosts; i++) {
  901.       if (hostPtr -> autoStart == YES)
  902.          [self loginToHost:hostPtr -> popUpName activate:NO];
  903.  
  904.       hostPtr = hostPtr -> nextHost;
  905.    }
  906.  
  907.    return self;
  908. }
  909.  
  910. /*---------------------------------------------------------------------------
  911. Fire up a Terminal or Stuart session for the user.
  912. -----------------------------------------------------------------------------*/
  913. - loginToHost:(const char *)buttonName activate:(BOOL)actWindow
  914. {
  915.    char            colsStr[16];
  916.    char           *comArgs[MAXCOMARGS];
  917.    char            command[1024];
  918.    char            errMsg[256];
  919.    int             i;
  920.    int             ind;
  921.    char            fontStr[16];
  922.    char            linesStr[16];
  923.    char            loginStr[256];
  924.    char            metaStr[16];
  925.    int             pid;
  926.    char           *shellPtr;
  927.    id              stuart;
  928.    int             slotNum;
  929.    char          **tempPtr;
  930.    char            xStr[16];
  931.    char            yStr[16];
  932.  
  933.    int             vfork (void);
  934.  
  935.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  936.  
  937.    slotNum = [self getHostSlotNum:buttonName];
  938.    if (slotNum < 0) {
  939.       NXRunAlertPanel (NULL, "Button name '%s' not found.", NULL, NULL, NULL, buttonName);
  940.       return self;
  941.    }
  942.  
  943.    ind = 0;
  944.    
  945.    hostPtr = begHost;
  946.    for (i = 0; i < slotNum; i++)
  947.       hostPtr = hostPtr -> nextHost;
  948.  
  949.    if (hostPtr -> appType == TERMINAL) {
  950.       strcpy (command, "/NextApps/Terminal.app/Terminal");
  951.  
  952.       comArgs[ind++] = "Terminal";
  953.  
  954.       comArgs[ind++] = "-Shell";
  955.  
  956.       if (strcmp (hostPtr -> hostName, "localhost") == 0) {
  957.      shellPtr = getenv ("SHELL");
  958.      if (shellPtr == NULL)
  959.         comArgs[ind++] = "/bin/csh";
  960.      else
  961.         comArgs[ind++] = shellPtr;
  962.       }
  963.       else {
  964.          switch (hostPtr -> protocolType) {
  965.          case RLOGIN:
  966.             strcpy (loginStr, "\"/usr/ucb/rlogin ");
  967.             strcat (loginStr, hostPtr -> hostName);
  968.         
  969.             if (*hostPtr -> loginName != '\0') {
  970.                strcat (loginStr, " -l ");
  971.                strcat (loginStr, hostPtr -> loginName);
  972.             }
  973.  
  974.             break;
  975.  
  976.          case TELNET:
  977.             strcpy (loginStr, "\"/usr/ucb/telnet ");
  978.             strcat (loginStr, hostPtr -> hostName);
  979.             break;
  980.  
  981.          case TN3270:
  982.             strcpy (loginStr, "\"/usr/ucb/tn3270 ");
  983.             strcat (loginStr, hostPtr -> hostName);
  984.             break;
  985.  
  986.          default:
  987.             break;
  988.          }
  989.  
  990.      strcat (loginStr, "\"");
  991.      comArgs[ind++] = loginStr;
  992.       }
  993.  
  994.       comArgs[ind++] = "-WinLocX";
  995.       sprintf (xStr, "%d", hostPtr -> locX);
  996.       comArgs[ind++] = xStr;
  997.  
  998.       comArgs[ind++] = "-WinLocY";
  999.       sprintf (yStr, "%d", hostPtr -> locY);
  1000.       comArgs[ind++] = yStr;
  1001.  
  1002.       comArgs[ind++] = "-Rows";
  1003.       sprintf (linesStr, "%d", hostPtr -> nLines);
  1004.       comArgs[ind++] = linesStr;
  1005.  
  1006.       comArgs[ind++] = "-Columns";
  1007.       sprintf (colsStr, "%d", hostPtr -> nCols);
  1008.       comArgs[ind++] = colsStr;
  1009.  
  1010.       comArgs[ind++] = "-NXFixedPitchFont";
  1011.       if (hostPtr -> fontType == COURIER)
  1012.      comArgs[ind++] = "Courier";
  1013.       else
  1014.      comArgs[ind++] = "Ohlfs";
  1015.  
  1016.       comArgs[ind++] = "-NXFixedPitchFontSize";
  1017.       sprintf (fontStr, "%d", hostPtr -> fontSize);
  1018.       comArgs[ind++] = fontStr;
  1019.  
  1020.       if (hostPtr -> meta != TMETADEF) {
  1021.      comArgs[ind++] = "-Meta";
  1022.      sprintf (metaStr, "%d", hostPtr -> meta);
  1023.      comArgs[ind++] = metaStr;
  1024.       }
  1025.  
  1026.       comArgs[ind++] = "-Translate";
  1027.       comArgs[ind++] = (hostPtr -> flags & TTRANSLAT) ? "YES" : "NO";
  1028.       
  1029.       comArgs[ind++] = "-Keypad";
  1030.       comArgs[ind++] = (hostPtr -> flags & TKEYPAD) ? "YES" : "NO";
  1031.       
  1032.       comArgs[ind++] = "-StrictEmulation";
  1033.       comArgs[ind++] = (hostPtr -> flags & TSTRICTEM) ? "YES" : "NO";
  1034.       
  1035.       comArgs[ind++] = "-Autowrap";
  1036.       comArgs[ind++] = (hostPtr -> flags & TAUTOWRAP) ? "YES" : "NO";
  1037.       
  1038.       comArgs[ind++] = "-Scrollback";
  1039.       comArgs[ind++] = (hostPtr -> flags & TSCROLLBK) ? "YES" : "NO";
  1040.       
  1041.       comArgs[ind++] = "-AutoFocus";
  1042.       comArgs[ind++] = (hostPtr -> flags & TAUTOFOCS) ? "YES" : "NO";
  1043.       
  1044.       comArgs[ind++] = "-SourceDotLogin";
  1045.       comArgs[ind++] = (hostPtr -> flags & TSOURCEDL) ? "YES" : "NO";
  1046.  
  1047.       comArgs[ind++] = "-CustomTitle";
  1048.       comArgs[ind++] = hostPtr -> hostName;
  1049.  
  1050.       comArgs[ind++] = NULL;
  1051.  
  1052.       /*** Gotta build a shell-like command under NeXT Release 3.1. */
  1053.  
  1054.       tempPtr = comArgs;
  1055.       while (*++tempPtr != NULL) {
  1056.      strcat (command, " ");
  1057.      strcat (command, *tempPtr);
  1058.       }
  1059.       
  1060.       if (debugLevel != DEBUGOFF)
  1061.      printf ("%s: %s\n",[NXApp appName], command);
  1062.  
  1063.       pid = vfork ();
  1064.       if (pid == 0) {
  1065.  
  1066.      system (command);
  1067.      exit (0);
  1068.  
  1069. #if 0    /*** execve worked under NeXT Release 2.x.  Doesn't work now. */
  1070.      code = execve (command, comArgs, environ);
  1071.  
  1072.      perror ([NXApp appName]);
  1073.      fprintf (stderr, "%s: Execve error code=%d.\n",[NXApp appName], code);
  1074.  
  1075.      _exit (0);
  1076. #endif
  1077.  
  1078.       }
  1079.    }
  1080.    else {
  1081.       stuart = [StuartSpeaker new];
  1082.  
  1083.       if (debugLevel != DEBUGOFF)
  1084.      printf ("Stuart");
  1085.      
  1086.       if (strcmp (hostPtr -> hostName, "localhost") != 0) {
  1087.  
  1088.          switch (hostPtr -> protocolType) {
  1089.          case RLOGIN:
  1090.             strcpy (loginStr, "rlogin ");
  1091.             strcat (loginStr, hostPtr -> hostName);
  1092.  
  1093.             if (*hostPtr -> loginName != '\0') {
  1094.                strcat (loginStr, " -l ");
  1095.                strcat (loginStr, hostPtr -> loginName);
  1096.             }
  1097.  
  1098.             break;
  1099.  
  1100.          case TELNET:
  1101.             strcpy (loginStr, "telnet ");
  1102.             strcat (loginStr, hostPtr -> hostName);
  1103.             break;
  1104.  
  1105.          case TN3270:
  1106.             strcpy (loginStr, "tn3270 ");
  1107.             strcat (loginStr, hostPtr -> hostName);
  1108.             break;
  1109.  
  1110.          default:
  1111.             break;
  1112.          }
  1113.  
  1114.      [self setStuartDefault:stuart default:"Shell" as:loginStr];
  1115.       }
  1116.  
  1117.       sprintf (xStr, "%d", hostPtr -> locX);
  1118.       [self setStuartDefault:stuart default:"WinLocX" as:xStr];
  1119.  
  1120.       sprintf (yStr, "%d", hostPtr -> locY);
  1121.       [self setStuartDefault:stuart default:"WinLocY" as:yStr];
  1122.  
  1123.       sprintf (linesStr, "%d", hostPtr -> nLines);
  1124.       [self setStuartDefault:stuart default:"Lines" as:linesStr];
  1125.  
  1126.       sprintf (colsStr, "%d", hostPtr -> nCols);
  1127.       [self setStuartDefault:stuart default:"Columns" as:colsStr];
  1128.  
  1129.       if (hostPtr -> fontType == COURIER)
  1130.      [self setStuartDefault:stuart default:"NXFixedPitchFont" as:"Courier"];
  1131.       else
  1132.      [self setStuartDefault:stuart default:"NXFixedPitchFont" as:"Ohlfs"];
  1133.  
  1134.       sprintf (fontStr, "%d", hostPtr -> fontSize);
  1135.       [self setStuartDefault:stuart default:"NXFixedPitchFontSize" as:fontStr];
  1136.  
  1137.       if (hostPtr -> meta != SMETADEF) {
  1138.      sprintf (metaStr, "%d", hostPtr -> meta);
  1139.      [self setStuartDefault:stuart default:"Meta" as:metaStr];
  1140.       }
  1141.  
  1142.       [self setStuartDefault:stuart default:"Strict" as:(hostPtr -> flags & SSTRICTEM) ? "YES" : "NO"];
  1143.       [self setStuartDefault:stuart default:"Keypad" as:(hostPtr -> flags & SKEYPAD) ? "YES" : "NO"];
  1144.       [self setStuartDefault:stuart default:"Scrollback" as:(hostPtr -> flags & SSCROLLBK) ? "YES" : "NO"];
  1145.       [self setStuartDefault:stuart default:"Translate" as:(hostPtr -> flags & STRANSLAT) ? "YES" : "NO"];
  1146.       [self setStuartDefault:stuart default:"Reverse" as:(hostPtr -> flags & SREVERSE) ? "YES" : "NO"];
  1147.       [self setStuartDefault:stuart default:"KeyboardFocus" as:(hostPtr -> flags & SKEYBDFOC) ? "YES" : "NO"];
  1148.       [self setStuartDefault:stuart default:"TerminalSpacing" as:(hostPtr -> flags & STERMSPAC) ? "YES" : "NO"];
  1149.       [self setStuartDefault:stuart default:"MouseFocus" as:(hostPtr -> flags & SMOUSEFOC) ? "YES" : "NO"];
  1150.       [self setStuartDefault:stuart default:"SourceDotLogin" as:(hostPtr -> flags & SSOURCEDL) ? "YES" : "NO"];
  1151.       [self setStuartDefault:stuart default:"TestExit" as:(hostPtr -> flags & STESTEXIT) ? "YES" : "NO"];
  1152.       [self setStuartDefault:stuart default:"WriteStuartrc" as:"NO"];
  1153.       [self setStuartDefault:stuart default:"Title" as:hostPtr -> hostName];
  1154.       [self setStuartDefault:stuart default:"MiniTitle" as:buttonName];
  1155.       [self setStuartDefault:stuart default:"Activate" as:actWindow ? "YES" : "NO"];
  1156.  
  1157.       if (debugLevel != DEBUGOFF)
  1158.      printf("\n");
  1159.       
  1160.       if ([stuart stuartConnectAndNew]) {
  1161.      strcpy (errMsg, "There was a problem communicating with the Stuart ");
  1162.      strcat (errMsg, "application.  (Speaker port unavailable.)  This may ");
  1163.      strcat (errMsg, "have occurred because Stuart is not installed on ");
  1164.      strcat (errMsg, "your system or because Stuart was slow in starting.");
  1165.  
  1166.      NXRunAlertPanel (NULL, errMsg, NULL, NULL, NULL, NULL);
  1167.       }
  1168.       
  1169.       [stuart free];
  1170.    }
  1171.    
  1172.    return self;
  1173. }
  1174.  
  1175. /*---------------------------------------------------------------------------
  1176. Set specified Stuart default value.
  1177. -----------------------------------------------------------------------------*/
  1178. - setStuartDefault:aStuart default:(const char *)defaultV as:(const char *)asV
  1179. {
  1180.    if (debugLevel != DEBUGOFF)
  1181.       printf(" -%s %s", defaultV, asV);
  1182.  
  1183.    [aStuart default:defaultV as:asV];
  1184.  
  1185.    return self;
  1186. }
  1187.  
  1188. /*---------------------------------------------------------------------------
  1189. Set debugging variable within object & in defaults data base.
  1190. -----------------------------------------------------------------------------*/
  1191. - setDebugLevel:(short int)debugNum
  1192. {
  1193.    int             code;
  1194.    char            defaultsDebugLevel[5];
  1195.  
  1196.    debugLevel = debugNum;       /* Update object's setting */
  1197.  
  1198.    if (debugNum == 1)
  1199.       strcpy (defaultsDebugLevel, "low");
  1200.    else if (debugNum == 2)
  1201.       strcpy (defaultsDebugLevel, "high");
  1202.    else
  1203.       strcpy (defaultsDebugLevel, "off");
  1204.  
  1205.    code = NXWriteDefault ([NXApp appName], "DebugLevel", defaultsDebugLevel);
  1206.  
  1207.    return self;
  1208. }
  1209.  
  1210. /*---------------------------------------------------------------------------
  1211. Open the configuration file.
  1212. -----------------------------------------------------------------------------*/
  1213. - (FILE *) openConfigFile:(const char *)mode
  1214. {
  1215.    const char     *configFile;  /* Configuration pathname */
  1216.    FILE           *fp;
  1217.  
  1218.    configFile = NXGetDefaultValue ([NXApp appName], "ConfigFile");
  1219.  
  1220.    if ((fp = fopen (configFile, mode)) == NULL) {
  1221.       if (debugLevel >= DEBUGHIGH)
  1222.          printf ("%s:Unable to open config file '%s' with mode '%s'.\n",
  1223.             [NXApp appName], configFile, mode);
  1224.       return NULL;
  1225.    }
  1226.  
  1227.    if (debugLevel >= DEBUGHIGH)
  1228.       printf ("%s:'%s' opened with mode '%s'.\n",
  1229.          [NXApp appName], configFile, mode);
  1230.  
  1231.    return fp;
  1232. }
  1233.  
  1234. /*---------------------------------------------------------------------------
  1235. Set configuration path variable within object & in defaults data base.
  1236. -----------------------------------------------------------------------------*/
  1237. - setConfigFile:(const char *)configFile
  1238. {
  1239.    const char     *configFileOld;
  1240.    FILE           *fp;
  1241.  
  1242.    if (strcmp (configFile,[self getConfigFile:self]) == 0)
  1243.       return self;
  1244.  
  1245.    if (index (configFile, ' ') != 0) {
  1246.       NXRunAlertPanel (NULL, "Blanks not allowed in pathname.", NULL, NULL,
  1247.          NULL);
  1248.       return self;
  1249.    }
  1250.  
  1251.    fp = fopen (configFile, "r");
  1252.    if (fp != NULL) {
  1253.       fclose (fp);
  1254.       if (NXRunAlertPanel (NULL, "The config file '%s' exists; OK to overwrite?",
  1255.         "Cancel", "OK", NULL, configFile) == NX_ALERTDEFAULT)
  1256.          return self;
  1257.    }
  1258.  
  1259.    fp = fopen (configFile, "w");
  1260.    if (fp == NULL) {
  1261.       NXRunAlertPanel (NULL, "Unable to open the config file '%s'.", NULL, NULL, NULL, configFile);
  1262.       return self;
  1263.    }
  1264.  
  1265.    configFileOld = NXGetDefaultValue ([NXApp appName], "ConfigFile");
  1266.    if (NXWriteDefault ([NXApp appName], "ConfigFile", configFile) == 0) {
  1267.       NXRunAlertPanel (NULL, "Unable to write to defaults data base.", NULL, NULL,
  1268.          NULL);
  1269.       return self;
  1270.    }
  1271.  
  1272.    [self writeConfigFile:self];
  1273.    unlink (configFileOld);
  1274.  
  1275.    return self;
  1276. }
  1277.  
  1278. /*---------------------------------------------------------------------------
  1279. Write the configuration file from our internal list.
  1280. -----------------------------------------------------------------------------*/
  1281. - writeConfigFile:sender
  1282. {
  1283.    int             i;
  1284.    struct hostEntry *hostPtr;   /* Pointer to host entry */
  1285.    FILE           *fp;
  1286.  
  1287.    fp = [self openConfigFile:"w"];
  1288.  
  1289.    hostPtr = begHost;
  1290.    for (i = 0; i < nHosts; i++) {
  1291.       fprintf (fp, "%d", CFGVERSION);
  1292.       fprintf( fp, "\t%s", hostPtr -> popUpName); 
  1293.       fprintf( fp, "\t%s", hostPtr -> hostName); 
  1294.       fprintf (fp, "\t%s", hostPtr -> loginName);
  1295.       fprintf (fp, "\t%d", hostPtr -> appType);
  1296.       fprintf (fp, "\t%d", hostPtr -> protocolType);
  1297.       fprintf (fp, "\t%d", hostPtr -> locX);
  1298.       fprintf (fp, "\t%d", hostPtr -> locY);
  1299.       fprintf (fp, "\t%d", hostPtr -> nLines);
  1300.       fprintf (fp, "\t%d", hostPtr -> nCols);
  1301.       fprintf (fp, "\t%d", hostPtr -> fontType);
  1302.       fprintf (fp, "\t%d", hostPtr -> fontSize);
  1303.       fprintf (fp, "\t%d", hostPtr -> autoStart);
  1304.       fprintf (fp, "\t%u", hostPtr -> flags);
  1305.       fprintf (fp, "\t%d", hostPtr -> meta);
  1306.       fprintf (fp, "\n");
  1307.  
  1308.       if (debugLevel == DEBUGMAX) {
  1309.          printf ("%s:(write #%d okay) version:%d\t%s\t%s\n",
  1310.             [NXApp appName], i + 1, CFGVERSION, hostPtr -> popUpName, hostPtr -> hostName);
  1311.          printf ("\tID:%s", hostPtr -> loginName);
  1312.          printf ("\tapp:%d", hostPtr -> appType);
  1313.          printf ("\tprot:%d", hostPtr -> protocolType);
  1314.          printf ("\tx:%d", hostPtr -> locX);
  1315.          printf ("\ty:%d", hostPtr -> locY);
  1316.          printf ("\n");
  1317.          printf ("\tlines:%d", hostPtr -> nLines);
  1318.          printf ("\tcols:%d", hostPtr -> nCols);
  1319.          printf ("\tfont:%d", hostPtr -> fontType);
  1320.          printf ("\tfontsize:%d", hostPtr -> fontSize);
  1321.          printf ("\n");
  1322.          printf ("\tautostart:%d", hostPtr -> autoStart); 
  1323.      printf ("\tflags:%u", hostPtr -> flags);
  1324.      printf ("\tmeta:%d", hostPtr -> meta);
  1325.      printf ("\n");
  1326.       }
  1327.  
  1328.       hostPtr = hostPtr -> nextHost;
  1329.    }
  1330.  
  1331.    fclose (fp);
  1332.  
  1333.    if (debugLevel >= DEBUGHIGH)
  1334.       printf ("%s: Config file written.  %d records in the file.\n",
  1335.          [NXApp appName], nHosts);
  1336.  
  1337.    return self;
  1338. }
  1339.  
  1340. @end
  1341.